package com.zhilei.intercept;

import com.zhilei.base.BaseInfoProperties;
import com.zhilei.exceptions.GraceException;
import com.zhilei.grace.result.ResponseStatusEnum;
import com.zhilei.untils.IPUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 配置短信的拦截器，在通过控制器之前；
 * 因为短信验证是系统的开始，不需要去校验用户状态，不需要过滤器对他进行过滤
 * 拦截器需要注册才能使用
 */
@Slf4j
@Order(value = 1)  // TODO 数字越小，优先级越高
public class SMSInterceptor extends BaseInfoProperties implements HandlerInterceptor {

    /**
     * 请求到达控制器之前
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {

        // 1. 获取请求头中的验证码
        // 使用ip的工具类去获得用户的ip地址
        String ip = IPUtil.getRequestIp(request);
        // 2. 在redis中获取存放的键是哪个
        boolean ipExist = redis.keyIsExist(MOBILE_SMSCODE + ":" + ip);
        // 校验如果不是空的，那么就是有值，对请求进行拦截；反之放行请求
        if (ipExist) {
            // 封装之后方法会抛出一个JSON的异常返回数据，不会影响下方的return false
            // 该异常沿着调用栈向上冒泡，最终被 Spring 的异常处理机制捕获
            // 具体来说是同一个请求链中，当请求发生异常时，Spring会查找是否有合适的异常处理器来处理这些异常
            // 当没有合适的异常捕获处理器的时候，会被spring的全局异常进行捕获
            GraceException.disPlay(ResponseStatusEnum.SMS_NEED_WAIT_ERROR);

            // 拦截请求
            return false;
        }

        // return true 放行请求
        // return false 拦截请求
        return true;
    }

    /**
     * 请求处理完成后，但在视图渲染之前被调用
     *
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    /**
     * 请求处理完成后被调用的方法
     * 请求完成后做一些资源释放或日志记录等处理
     *
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}







